package zhongbo.java.air.airingestion.listener;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import zhongbo.java.air.airingestion.config.RedisListenerConfig;
import zhongbo.java.air.airingestion.dto.AirFlightPathDto;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

@Component
@Slf4j
public class RedisLogSubscribeLogChanelListener implements MessageListener {

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private RedisLogChanelPublisher redisLogChanelPublisher;

    @Override
    public void onMessage(Message message, byte[] bytes) {
        String channel = new String(message.getChannel()); // 获取频道名称
        String rawMsg = new String(message.getBody());
        log.info("接收到频道 [{}] 原始航迹数据: {}", channel, rawMsg);

        AirFlightPathDto flightPath = convertToFlightPath(rawMsg);
        if (flightPath != null) {
            log.info("接收到频道 [{}] 装换后的航迹数据: {}", channel, flightPath);
        }
        //flightPath转换为json
        String json = null;
        try {
            json = objectMapper.writeValueAsString(flightPath);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        redisLogChanelPublisher.publishMessage(RedisListenerConfig.LOG_CHANEL,json);

    }

    private AirFlightPathDto convertToFlightPath(String rawMsg) {
        AirFlightPathDto flightPath = new AirFlightPathDto();
        if (rawMsg == null || rawMsg.isEmpty()){
            throw new RuntimeException("原始航迹数据为空");
        }
        JSONObject jsonObject = JSONUtil.parseObj(rawMsg);

        if (jsonObject.getStr("icao") == null){
            flightPath.setIcao_code("");
        }else {
            String icaoCode = jsonObject.getStr("icao");
            flightPath.setIcao_code(icaoCode);
        }


        if (jsonObject.getJSONArray("trace") == null || jsonObject.getJSONArray("trace").isEmpty()){
            throw new RuntimeException("原始航迹数据trace为空");
        }
        JSONArray jsonArray = jsonObject.getJSONArray("trace");

        if (jsonArray.get(0) == null){
            throw new RuntimeException("原始航迹数据trace[0]为空");
        }
        if (jsonObject.getDouble("timestamp") == null){
            throw new RuntimeException("原始航迹数据timestamp为空");
        }
        //时间戳字段, 先获取字符串, 判断字符串长度是否==13, 如果等于13, 就不需要乘以1000; 直接new Date(timeMs);否则就需要乘以1000;
        // 替换原代码中的时间戳处理逻辑
        String timestampStr = jsonObject.getStr("timestamp");
        BigDecimal timestampBD = new BigDecimal(timestampStr); // 精确构造

        Object firstElement = jsonArray.get(0);
        BigDecimal firstElementBD = null;
        if (firstElement instanceof BigDecimal) {
            firstElementBD = (BigDecimal) firstElement;
        } else if (firstElement instanceof Double) {
            firstElementBD = BigDecimal.valueOf((Double) firstElement);
        } else {
            throw new RuntimeException("trace[0]类型不合法，应为数字类型");
        }

// 根据 timestampStr 长度处理
        if (timestampStr.length() == 13) {
            // 毫秒级：直接相加
            BigDecimal finalTimeMs = firstElementBD.add(timestampBD);
            Date data = DateUtil.date(finalTimeMs.longValue());
            flightPath.setTimestamp(data);
        } else {
            // 秒级：转为毫秒后相加
            BigDecimal firstMs = firstElementBD.multiply(BigDecimal.valueOf(1000));
            BigDecimal timestampMs = timestampBD.multiply(BigDecimal.valueOf(1000));
            BigDecimal finalTimeMs = firstMs.add(timestampMs);
            Date data = DateUtil.date(finalTimeMs.longValue());
            flightPath.setTimestamp(data);
            log.info("最终时间戳的毫秒值：{}", data.getTime()); // 输出 long 类型的毫秒
            log.info("格式化后的时间：{}", DateUtil.format(data, "yyyy-MM-dd HH:mm:ss.SSS"));
        }


        Object latitudeObj = jsonArray.get(1);
        if (latitudeObj instanceof Number) { // 检查是否为数值类型（包括BigDecimal）
            Double latitude = ((Number) latitudeObj).doubleValue();
            flightPath.setLatitude(latitude);
        } else {
            throw new RuntimeException("纬度字段类型错误，应为数值类型");
        }

        Object longitudeObj = jsonArray.get(2);
        if (longitudeObj instanceof Number) { // 检查是否为数值类型（包括BigDecimal）
            Double longitude = ((Number) longitudeObj).doubleValue();
            flightPath.setLongitude(longitude);
        } else {
            throw new RuntimeException("经度字段类型错误，应为数值类型");
        }

        Object altitudeObj = jsonArray.get(3);
        if (altitudeObj instanceof Number) { // 检查是否为数值类型（包括BigDecimal）
            Double altitude = ((Number) altitudeObj).doubleValue();
            flightPath.setAltitude(altitude);
        } else {
            throw new RuntimeException("高度字段类型错误，应为数值类型");
        }

        Object speedObj = jsonArray.get(4);
        if (speedObj instanceof Number){
            Double speed = ((Number) speedObj).doubleValue();
            flightPath.setSpeed(speed);
        }

        Object headingObj = jsonArray.get(5);
        if (headingObj instanceof Number){
            Double heading = ((Number) headingObj).doubleValue();
            flightPath.setHeading(heading);
        }

        String sourceType = null;
        //判断是否为json格式
        if (jsonArray.get(8) == null){
            flightPath.setSource_type("");
        }
        if (jsonArray.get(8) instanceof JSON){
            JSONObject jsonObject1 = JSONUtil.parseObj(jsonArray.get(8));
            if (jsonObject1.getStr("type") == null){
                throw new RuntimeException("原始航迹数据sourceType为空");
            }
            sourceType = jsonObject1.getStr("type");
            flightPath.setSource_type(sourceType);
        }
        return flightPath;
    }
}